/** @type {Object} 网络请求 */
import axios from 'axios'
import Util from './util.js'
import Message from './message.js'
import Store from '@/vuex/store.js'
import Router from '@/router'
import SparkMD5 from 'spark-md5'
import {
  saveAs
} from 'file-saver';

const codeMessage = {
  200: '服务器成功返回请求的数据',
  201: '新建或修改数据成功',
  202: '一个请求已经进入后台排队（异步任务）',
  204: '删除数据成功',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作',
  401: '用户没有权限（令牌、用户名、密码错误）',
  403: '用户得到授权，但是访问是被禁止的',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作',
  406: '请求的格式不可得',
  410: '请求的资源被永久删除，且不会再得到的',
  422: '当创建一个对象时，发生一个验证错误',
  500: '服务器发生错误，请检查服务器',
  502: '网关错误',
  503: '服务不可用，服务器暂时过载或维护',
  504: '网关超时'
}

const http = {
  /**
   * 获取请求实例
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-15
   */
  instance: (_config) => {
    _config = Util.isJson(_config) ? _config : {}
    const _init = {
      baseURL: process.env.VUE_APP_API_HOST
    }
    Util.extend(_init, _config)
    axios.defaults.headers.common['Is-Axios'] = 1;
    axios.defaults.headers.common['E-DEVICE-TYPE'] = 'manage';
    axios.defaults.headers.common['E-APP-ID'] = process.env.VUE_APP_ID;
    axios.defaults.headers.common['E-USER-AK'] = Store.getters['login/token'].ak
    axios.defaults.headers.common['E-USER-SK'] = Store.getters['login/token'].sk

    // 此处待完善,需要传递用户的token,测试阶段,直接传用户UID=1
    // axios.defaults.headers.common['Auth-Token'] = Store.state.login.token;
    const instance = axios.create(_init)
    // 设置请求拦截器
    instance.interceptors.request.use(
      config => {
        let params = config.data || config.params;
        if (!Util.isObject(params)) {
          params = {};
        }
        config.headers = {
          ...config.headers,
          ...http.signature(params)
        }

        return config;
      });
    instance.interceptors.response.use(response => {
      return Promise.resolve(response)
    }, error => {
      Store.dispatch('setLoading', 0);
      if (error === undefined || error.code === 'ECONNABORTED') {
        Message.error('服务请求超时')
        return Promise.reject(error)
      }
      const {
        response: {
          status,
          statusText,
          data: {
            msg = ''
          }
        }
      } = error
      // 如果是401错误
      if (status === 401) {
        Store.dispatch('login/setLogout');
        Router.push({
          path: '/login'
        });
      } else {
        const msgText = msg || codeMessage[status] || statusText;
        // Message.error(`${status}:${msgText}`)
        Message.error(`${msgText}`)
      }
      return Promise.reject(error);
    });
    return instance;
  },
  /**
   * 携带body参数
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-15
   * @param    {string}   uri 请求地址,不包含根域名
   * @param    {any}  data    请求body数据
   * @param    {function} callbackSuccess 成功回调处理方法
   * @param    {function} callbackError   失败回调处理方法
   * @param    {boolen} loading 指定为false时,不显示loading,默认0.6s后显示
   * @return   处理结果 | 未指定回调方法时,返回后端响应的数据
   */
  sendWidthData: function(uri, data, callbackSuccess, callbackError, loading, config) {
    var loadingVist = false;
    if (!Util.isFalse(loading)) {
      Store.dispatch('setLoading', true, {
        root: true
      });
      loadingVist = true;
    }
    return this.instance(config).post(uri, data).then(function(response) {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      if (response.data.code == 1) {
        // 后台处理成功,是否定义了成功的处理方法
        if (Util.isFunction(callbackSuccess)) {
          return callbackSuccess(response.data);
        }
      } else {
        // 后台处理失败,是否定义了失败的处理方法
        if (Util.isFunction(callbackError)) {
          return callbackError(response.data);
        }
      }
      // 默认处理
      return response.data;
    }).catch(function() {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      return false;
    });
  },
  /**
   * url参数
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-15
   * @param    {string}   uri 请求地址,不包含根域名
   * @param    {any}  params  请求携带的params数据,会拼接到url
   * @param    {function} callbackSuccess 成功回调处理方法
   * @param    {function} callbackError   失败回调处理方法
   * @param    {boolen} loading 指定为false时,不显示loading,默认0.6s后显示
   * @return   处理结果 | 未指定回调方法时,返回后端响应的数据
   */
  sendWidthParams: function(uri, params, callbackSuccess, callbackError, loading) {
    var loadingVist = false;
    if (!Util.isFalse(loading)) {
      Store.dispatch('setLoading', true, {
        root: true
      });

      loadingVist = true;
    }
    return this.instance().get(uri, {
      params: params
    }).then((response) => {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      if (Util.isJson(response.data)) {
        if (response.data.code == 1) {
          // 后台处理成功,是否定义了成功的处理方法
          if (Util.isFunction(callbackSuccess)) {
            return callbackSuccess(response.data);
          }
        } else {
          // 后台处理失败,是否定义了失败的处理方法
          if (Util.isFunction(callbackError)) {
            return callbackError(response.data);
          }
        }
        // 默认处理
        return response.data;
      } else {
        if (Util.isFunction(callbackSuccess)) {
          return callbackSuccess(response.data);
        }
      }
    }).catch(_ => {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      return false;
    });
  },
  /**
   * get请求
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-15
   * @param    {string}   uri 请求地址,不包含根域名
   * @param    {any}  params  请求携带的params数据,会拼接到url
   * @param    {function} callbackSuccess 成功回调处理方法
   * @param    {function} callbackError   失败回调处理方法
   * @param    {boolean} loading 是否显示loading层,为false时不显示
   * @return   处理结果 | 未指定回调方法时,返回后端响应的数据
   */
  get: function(uri, params, callbackSuccess, callbackError, loading) {
    return this.sendWidthParams(uri, params, callbackSuccess, callbackError, loading);
  },
  /**
   * post请求
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-15
   * @param    {string}   uri 请求地址,不包含根域名
   * @param    {any}  data    请求body数据
   * @param    {function} callbackSuccess 成功回调处理方法
   * @param    {function} callbackError   失败回调处理方法
   * @param    {boolean} loading 是否显示loading层,为false时不显示
   * @param    {object|json} config 请求配置
   * @return   处理结果 | 未指定回调方法时,返回后端响应的数据
   */
  post: function(uri, data, callbackSuccess, callbackError, loading, config) {
    return this.sendWidthData(uri, data, callbackSuccess, callbackError, loading, config);
  },
  /**
   * delete请求
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-15
   * @param    {string}   uri 请求地址,不包含根域名
   * @param    {any}  params  请求携带的params数据,会拼接到url
   * @param    {function} callbackSuccess 成功回调处理方法
   * @param    {function} callbackError   失败回调处理方法
   * @param    {boolean} loading 是否显示loading层,为false时不显示
   * @return   处理结果 | 未指定回调方法时,返回后端响应的数据
   */
  delete: function(uri, params, callbackSuccess, callbackError, loading) {
    var loadingVist = false;
    if (!Util.isFalse(loading)) {
      Store.dispatch('setLoading', true, {
        root: true
      });

      loadingVist = true;
    }
    return this.instance().delete(uri, {
      params: params
    }).then((response) => {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      if (response.data.code == 1) {
        // 后台处理成功,是否定义了成功的处理方法
        if (Util.isFunction(callbackSuccess)) {
          return callbackSuccess(response.data);
        } else {
          response = response.data;
          Message.success(response.msg);
        }
      } else {
        // 后台处理失败,是否定义了失败的处理方法
        if (Util.isFunction(callbackError)) {
          return callbackError(response.data);
        } else {
          response = response.data;
          Message.error(response.msg);
        }
      }
      // 默认处理
      return response.data;
    }).catch(_ => {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      return false;
    });
  },
  /**
   * put请求
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-15
   * @param    {string}   uri 请求地址,不包含根域名
   * @param    {any}  data    请求body数据
   * @param    {function} callbackSuccess 成功回调处理方法
   * @param    {function} callbackError   失败回调处理方法
   * @param    {boolean} loading 是否显示loading层,为false时不显示
   * @return   处理结果 | 未指定回调方法时,返回后端响应的数据
   */
  put: function(uri, data, callbackSuccess, callbackError, loading) {
    var loadingVist = false;
    if (!Util.isFalse(loading)) {
      Store.dispatch('setLoading', true, {
        root: true
      });

      loadingVist = true;
    }
    return this.instance().put(uri, data).then(function(response) {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      if (response.data.code == 1) {
        // 后台处理成功,是否定义了成功的处理方法
        if (Util.isFunction(callbackSuccess)) {
          return callbackSuccess(response.data);
        }
      } else {
        // 后台处理失败,是否定义了失败的处理方法
        if (Util.isFunction(callbackError)) {
          return callbackError(response.data);
        }
      }
      // 默认处理
      return response.data;
    }).catch(function() {
      loadingVist && Store.dispatch('setLoading', false, {
        root: true
      });
      return false;
    });
  },
  /**
   * 通用入口,
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-16
   * @param    {string}                       method          请方式
   * 其他参数见各个请求方法
   */
  send: function(method, uri, data, callbackSuccess, callbackError, loading) {
    method = method.toLowerCase();
    /* eslint-disable */
    return eval('this.' + method + '(uri,data,callbackSuccess,callbackError,loading)');
  },
  /**
   * 下载word文件
   *
   * @param {Object} uri
   * @param {Object} data
   * @param {Object} savename
   */
  downloadWord: function(uri, data) {
    return new Promise((resolve, reject) => {
      this.instance({
        responseType: 'blob'
      }).post(uri, data).then(function(response) {
        if (response.data.type == 'application/json') {
          response.data.text().then(function(text) {
            // 将文本转换为JSON对象
            var jsonData = JSON.parse(text);
            reject(jsonData.msg || '下载文件出错')
          }).catch(function(error) {
            reject('Error reading Blob as text');
          });

        } else {
          const {
            data
          } = response;
          // 处理文件名称
          const disposition = response.headers['content-disposition'] ||
              response.headers['Content-Disposition'];
          var filename = '下载.docx';
          if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) {
              filename = decodeURI(matches[1].replace(/['"]/g, ''));
            }
          }
          // 保存文件
          if (data) {
            const blob = new Blob([data], {
              type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
            })
            saveAs(blob, filename);
            resolve();
          }
          reject('保存本地文件失败')
        }
      }).catch(function() {
        reject('下载文件失败');
      });
    });
  },
  /**
   * 下载excel
   * @param uri
   * @param data
   * @returns {Promise<unknown>}
   */
  downloadExcel: function(uri, data) {
    return new Promise((resolve, reject) => {
      this.instance({
        responseType: 'blob'
      }).post(uri, data).then(function(response) {

        if (response.data.type == 'application/json') {
          response.data.text().then(function(text) {
            // 将文本转换为JSON对象
            var jsonData = JSON.parse(text);
            reject(jsonData.msg || '暂无可用数据导出')
          }).catch(function(error) {
            reject('Error reading Blob as text');
          });

        } else {
          const {
            data
          } = response;
          // 处理文件名称
          const disposition = response.headers['content-disposition'] ||
            response.headers['Content-Disposition'];
          var filename = '下载.xlsx';
          if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) {
              filename = decodeURI(matches[1].replace(/['"]/g, ''));
            }
          }
          // 保存文件
          if (data) {
            const blob = new Blob([data], {
              type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            })
            saveAs(blob, filename);
            resolve();
          }
          reject('保存本地文件失败')
        }
      }).catch(error => {
        reject(error || '下载文件失败');
      });
    });
  },
  signature: function(params) {
    const nonce = Math.random().toString(32).substr(4);
    const timestamp = Math.round(new Date() / 1000);
    const signString = process.env.VUE_APP_KEY + '|' + Util.objKeySort(params) + '|' + timestamp + '|' + nonce;
    // console.log(signString);
    const sign = SparkMD5.hash(signString).toUpperCase()

    return {
      'E-APP-TIMESTAMP': timestamp,
      'E-APP-NONCE': nonce,
      'E-APP-SIGN': sign
    }
  }
}

export default http
